<template>
  <teleport to="body">
    <div class="fixed z-50 top-24 right-0 w-96 bg-transparent">
      <transition-group
        tag="div"
        enter-active-class="transition duration-1000 ease-in"
        enter-from-class="opacity-0"
        enter-to-class="opacity-100"
        leave-active-class="transition duration-300 ease-in"
        leave-from-class="opacity-100"
        leave-to-class="opacity-0"
      >
        <z-notice
          v-for="notice of notices"
          :key="notice.name"
          :name="notice.name"
          :type="notice.type"
          :title="notice.title"
          :message="notice.message"
          :duration="notice.duration"
          @close="remove"
        />
      </transition-group>
    </div>
  </teleport>
  <slot></slot>
</template>
<script lang="ts">
import { defineComponent, ref, Ref, provide, inject, InjectionKey } from "vue";
import ZNotice, { NoticeType } from "./ZNotice.vue";

interface Notice {
  name: string;
  type: NoticeType;
  title: string;
  message: string;
  duration?: number;
}
type NoticeOption = { title?: string; duration?: number };
export type NoticeFn = (message: string, option?: NoticeOption) => void;
export interface Notification {
  success: NoticeFn;
  info: NoticeFn;
  warning: NoticeFn;
  error: NoticeFn;
}
const notificationInjectKey: InjectionKey<Notification> =
  Symbol("notification");

export const useNotification = () => inject(notificationInjectKey);

export default defineComponent({
  name: "ZNotification",
  components: {
    ZNotice,
  },
  props: {
    duration: {
      type: Number,
      default: 2500,
    },
  },
  setup(props) {
    let count = 0;
    const notices: Ref<Array<Notice>> = ref([]),
      createNotice = (type: NoticeType, defaultTitle: string) => {
        return (message: string, option: NoticeOption = {}) => {
          const { title = defaultTitle, duration = props.duration } = option;
          notices.value.unshift({
            name: "z-n" + count++,
            type,
            title,
            message,
            duration,
          });
        };
      },
      success = createNotice("success", "成功"),
      info = createNotice("info", "提示"),
      warning = createNotice("warning", "警告"),
      error = createNotice("error", "错误"),
      remove = (name: string) => {
        notices.value = notices.value.filter((val) => val.name != name);
      };
    provide(notificationInjectKey, { success, info, warning, error });
    return {
      notices,
      remove,
    };
  },
});
</script>
